using BepuUtilities;
using BepuUtilities.Memory;
using DemoRenderer;
using DemoUtilities;
using System;

namespace Demos
{
    public class GameLoop : IDisposable
    {
        public Window Window { get; private set; }
        public Input Input { get; private set; }
        public Camera Camera { get; private set; }
        public RenderSurface Surface { get; private set; }
        public Renderer Renderer { get; private set; }
        public DemoHarness DemoHarness { get; set; }
        public BufferPool Pool { get; } = new BufferPool();

        public GameLoop(Window window)
        {
            Window = window;
            Input = new Input(window, Pool);
            Surface = new RenderSurface(window.Handle, window.Resolution, enableDeviceDebugLayer: false);
            Renderer = new Renderer(Surface);
            Camera = new Camera(window.Resolution.X / (float)window.Resolution.Y, (float)Math.PI / 3, 0.01f, 100000);
        }

        void Update(float dt)
        {
            Input.Start();
            if (DemoHarness != null)
            {
                // 我们将让代理的逻辑处理可变的时间步长。
                DemoHarness.Update(dt);
                // 目前,渲染只是按顺序进行。稍后,我们可能想要用固定的时间步长或其他方法来更多地区分它。也许吧。
                DemoHarness.Render(Renderer);
            }
            Renderer.Render(Camera);
            Surface.Present();
            Input.End();
        }

        public void Run(DemoHarness harness)
        {
            DemoHarness = harness;
            Window.Run(Update, OnResize);
        }

        private void OnResize(Int2 resolution)
        {
            // 我们只是在演示中不支持真正的全屏。那是非常没有意义的。
            Renderer.Surface.Resize(resolution, false);
            Camera.AspectRatio = resolution.X / (float)resolution.Y;
            DemoHarness?.OnResize(resolution);
        }

        bool disposed;
        public void Dispose()
        {
            if (!disposed)
            {
                disposed = true;
                Input.Dispose();
                Renderer.Dispose();
                Pool.Clear();
                // 请注意,我们并不拥有该窗口。
            }
        }
    }
}
